#define __MQTT_TASK_C_
#include "mqtt_task.h"
#include "MQTTClient.h"
#include "cJSON.h"

// #define MQTT_ADDRESS                       "192.168.1.2"
#define MQTT_ADDRESS                       "wx.ai-thinker.com"
#define MQTT_PORT                          1883
#define MQTT_CLIENTID                      "SimpleClient"
#define MQTT_TOPIC                         "mytopic"

#define MQTT_PUB_TOPIC_STR_PM25            "homeassistant/sensor/pm25_device/config"
#define MQTT_PUB_TOPIC_STR_CO2             "homeassistant/sensor/co2_device/config"
#define MQTT_PUB_TOPIC_STR_PM10            "homeassistant/sensor/pm10_device/config"
#define MQTT_PUB_TOPIC_STR_PM1_0           "homeassistant/sensor/pm1_0_device/config"
#define MQTT_PUB_TOPIC_STR_ILLU            "homeassistant/sensor/illuminance_device/config"

#define MQTT_PUB_TOPIC_STR_AVAILABLE_PM25  "homeassistant/sensor/status"
#define MQTT_PUB_TOPIC_STR_AVAILABLE_CO2   "homeassistant/sensor/status"
#define MQTT_PUB_TOPIC_STR_AVAILABLE_PM10  "homeassistant/sensor/status"
#define MQTT_PUB_TOPIC_STR_AVAILABLE_PM1_0 "homeassistant/sensor/status"
#define MQTT_PUB_TOPIC_STR_AVAILABLE_ILLU  "homeassistant/sensor/status"

#define MQTT_PUB_TOPIC_STR_VAULE_PM25      "homeassistant/sensor/pm25_device/state"
#define MQTT_PUB_TOPIC_STR_VAULE_CO2       "homeassistant/sensor/co2_device/state"
#define MQTT_PUB_TOPIC_STR_VAULE_PM10      "homeassistant/sensor/pm10_device/state"
#define MQTT_PUB_TOPIC_STR_VAULE_PM1_0     "homeassistant/sensor/pm1_0_device/state"
#define MQTT_PUB_TOPIC_STR_VAULE_ILLU      "homeassistant/sensor/illuminance_device/state"

TaskHandle_t mqtt_task_xhandle = NULL;
volatile static uint8_t mqtt_start_flag = 1;

static volatile Network n;
static volatile MQTTClient mqtt_client;
static volatile unsigned char buf[1000];
static volatile unsigned char readbuf[1000];

void messageArrived(MessageData* md)
{
    MQTTMessage* m = md->message;
    printf("payload:%s\r\n", m->payload);
}

void mqtt_client_send(uint8_t* publish_str, uint8_t* buf, uint16_t length)
{
    int rc = 0;
    // 发布消息
    MQTTMessage pubmsg;
    pubmsg.payload = buf;       // 设置消息内容
    pubmsg.payloadlen = length; // 设置消息长度
    pubmsg.qos = 2;             // 设置消息质量服务(QoS)
    pubmsg.retained = 0;        // 设置是否保留消息

    // 使用MQTTPublish函数发布消息
    rc = MQTTPublish(&mqtt_client, publish_str, &pubmsg); // 替换"your_topic_name"为你要发布的主题

    if (rc != SUCCESS) {
        printf("Message publish failed with code %d\r\n", rc);
    }
}

void mqtt_pub_enable_pm25_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_PM25, "online", strlen("online"));
}

void mqtt_pub_disable_pm25_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_PM25, "offline", strlen("offline"));
}

void mqtt_pub_enable_co2_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_CO2, "online", strlen("online"));
}

void mqtt_pub_disable_co2_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_CO2, "offline", strlen("offline"));
}

void mqtt_pub_enable_pm10_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_PM10, "online", strlen("online"));
}

void mqtt_pub_disable_pm10_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_PM10, "offline", strlen("offline"));
}

void mqtt_pub_enable_pm1_0_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_PM1_0, "online", strlen("online"));
}

void mqtt_pub_disable_pm1_0_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_PM1_0, "offline", strlen("offline"));
}

void mqtt_pub_enable_illu_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_ILLU, "online", strlen("online"));
}

void mqtt_pub_disable_illu_send(void)
{
    mqtt_client_send(MQTT_PUB_TOPIC_STR_AVAILABLE_ILLU, "offline", strlen("offline"));
}

// 用于发送PM25实体
void mqtt_pub_payload_pm25_send(void)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加属性
    cJSON_AddStringToObject(root, "name", "pm25_device");
    cJSON_AddStringToObject(root, "device_class", "pm25");
    cJSON_AddStringToObject(root, "command_topic", "homeassistant/sensor/pm25_device/set");
    cJSON_AddStringToObject(root, "state_topic", "homeassistant/sensor/pm25_device/state");
    cJSON_AddStringToObject(root, "unique_id", "pm25_device");
    cJSON_AddStringToObject(root, "availability_topic", "homeassistant/sensor/status");
    cJSON_AddStringToObject(root, "payload_available", "online");
    cJSON_AddStringToObject(root, "payload_not_available", "offline");
    cJSON_AddStringToObject(root, "unit_of_measurement", "µg/m³");
    cJSON_AddStringToObject(root, "value_template", "{{ value_json.pm25 }}");

    // 添加 device 对象
    cJSON* device = cJSON_CreateObject();
    cJSON_AddStringToObject(device, "name", "rs485");
    cJSON_AddStringToObject(device, "manufacturer", "Ai-Thinker");
    cJSON_AddStringToObject(device, "model", "rs485");
    cJSON_AddStringToObject(device, "sw_version", "1.0.0");

    cJSON_AddItemToObject(root, "device", device);

    // 添加 identifiers 数组
    cJSON* identifiersArray = cJSON_CreateArray();
    cJSON_AddItemToArray(identifiersArray, cJSON_CreateString("01"));
    cJSON_AddItemToObject(device, "identifiers", identifiersArray);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    // 打印生成的 JSON 字符串
    mqtt_client_send(MQTT_PUB_TOPIC_STR_PM25, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_payload_co2_send(void)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加属性
    cJSON_AddStringToObject(root, "name", "co2_device");
    cJSON_AddStringToObject(root, "device_class", "carbon_dioxide");
    cJSON_AddStringToObject(root, "command_topic", "homeassistant/sensor/co2_device/set");
    cJSON_AddStringToObject(root, "state_topic", "homeassistant/sensor/co2_device/state");
    cJSON_AddStringToObject(root, "unique_id", "co2_device");
    cJSON_AddStringToObject(root, "availability_topic", "homeassistant/sensor/status");
    cJSON_AddStringToObject(root, "payload_available", "online");
    cJSON_AddStringToObject(root, "payload_not_available", "offline");
    cJSON_AddStringToObject(root, "unit_of_measurement", "ppm");
    cJSON_AddStringToObject(root, "value_template", "{{ value_json.pm25 }}");

    // 添加 device 对象
    cJSON* device = cJSON_CreateObject();
    cJSON_AddStringToObject(device, "name", "rs485");
    cJSON_AddStringToObject(device, "manufacturer", "Ai-Thinker");
    cJSON_AddStringToObject(device, "model", "rs485");
    cJSON_AddStringToObject(device, "sw_version", "1.0.0");

    cJSON_AddItemToObject(root, "device", device);

    // 添加 identifiers 数组
    cJSON* identifiersArray = cJSON_CreateArray();
    cJSON_AddItemToArray(identifiersArray, cJSON_CreateString("01"));
    cJSON_AddItemToObject(device, "identifiers", identifiersArray);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    // 打印生成的 JSON 字符串
    mqtt_client_send(MQTT_PUB_TOPIC_STR_CO2, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_payload_pm10_send(void)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加属性
    cJSON_AddStringToObject(root, "name", "pm10_device");
    cJSON_AddStringToObject(root, "device_class", "pm10");
    cJSON_AddStringToObject(root, "command_topic", "homeassistant/sensor/pm10_device/set");
    cJSON_AddStringToObject(root, "state_topic", "homeassistant/sensor/pm10_device/state");
    cJSON_AddStringToObject(root, "unique_id", "pm10_device");
    cJSON_AddStringToObject(root, "availability_topic", "homeassistant/sensor/status");
    cJSON_AddStringToObject(root, "payload_available", "online");
    cJSON_AddStringToObject(root, "payload_not_available", "offline");
    cJSON_AddStringToObject(root, "unit_of_measurement", "µg/m³");
    cJSON_AddStringToObject(root, "value_template", "{{ value_json.pm25 }}");
    // 添加 device 对象
    cJSON* device = cJSON_CreateObject();
    cJSON_AddStringToObject(device, "name", "rs485");
    cJSON_AddStringToObject(device, "manufacturer", "Ai-Thinker");
    cJSON_AddStringToObject(device, "model", "rs485");
    cJSON_AddStringToObject(device, "sw_version", "1.0.0");

    cJSON_AddItemToObject(root, "device", device);

    // 添加 identifiers 数组
    cJSON* identifiersArray = cJSON_CreateArray();
    cJSON_AddItemToArray(identifiersArray, cJSON_CreateString("01"));
    cJSON_AddItemToObject(device, "identifiers", identifiersArray);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    // 打印生成的 JSON 字符串
    // printf("%s\n", jsonString);
    mqtt_client_send(MQTT_PUB_TOPIC_STR_PM10, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_payload_pm1_0_send(void)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加属性
    cJSON_AddStringToObject(root, "name", "pm1_0_device");
    cJSON_AddStringToObject(root, "device_class", "pm1");
    cJSON_AddStringToObject(root, "command_topic", "homeassistant/sensor/pm1_0_device/set");
    cJSON_AddStringToObject(root, "state_topic", "homeassistant/sensor/pm1_0_device/state");
    cJSON_AddStringToObject(root, "unique_id", "pm1_0_device");
    cJSON_AddStringToObject(root, "availability_topic", "homeassistant/sensor/status");
    cJSON_AddStringToObject(root, "payload_available", "online");
    cJSON_AddStringToObject(root, "payload_not_available", "offline");
    cJSON_AddStringToObject(root, "unit_of_measurement", "µg/m³");
    cJSON_AddStringToObject(root, "value_template", "{{ value_json.pm25 }}");

    // 添加 device 对象
    cJSON* device = cJSON_CreateObject();
    cJSON_AddStringToObject(device, "name", "rs485");
    cJSON_AddStringToObject(device, "manufacturer", "Ai-Thinker");
    cJSON_AddStringToObject(device, "model", "rs485");
    cJSON_AddStringToObject(device, "sw_version", "1.0.0");

    cJSON_AddItemToObject(root, "device", device);

    // 添加 identifiers 数组
    cJSON* identifiersArray = cJSON_CreateArray();
    cJSON_AddItemToArray(identifiersArray, cJSON_CreateString("01"));
    cJSON_AddItemToObject(device, "identifiers", identifiersArray);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    // 打印生成的 JSON 字符串
    // printf("%s\n", jsonString);
    mqtt_client_send(MQTT_PUB_TOPIC_STR_PM1_0, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_payload_illu_send(void)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加属性
    cJSON_AddStringToObject(root, "name", "illuminance_device");
    cJSON_AddStringToObject(root, "device_class", "illuminance");
    cJSON_AddStringToObject(root, "command_topic", "homeassistant/sensor/illuminance_device/set");
    cJSON_AddStringToObject(root, "state_topic", "homeassistant/sensor/illuminance_device/state");
    cJSON_AddStringToObject(root, "unique_id", "illuminance_device");
    cJSON_AddStringToObject(root, "availability_topic", "homeassistant/sensor/status");
    cJSON_AddStringToObject(root, "payload_available", "online");
    cJSON_AddStringToObject(root, "payload_not_available", "offline");
    cJSON_AddStringToObject(root, "unit_of_measurement", "lux³");
    cJSON_AddStringToObject(root, "value_template", "{{ value_json.pm25 }}");

    // 添加 device 对象
    cJSON* device = cJSON_CreateObject();
    cJSON_AddStringToObject(device, "name", "rs485");
    cJSON_AddStringToObject(device, "manufacturer", "Ai-Thinker");
    cJSON_AddStringToObject(device, "model", "rs485");
    cJSON_AddStringToObject(device, "sw_version", "1.0.0");

    cJSON_AddItemToObject(root, "device", device);

    // 添加 identifiers 数组
    cJSON* identifiersArray = cJSON_CreateArray();
    cJSON_AddItemToArray(identifiersArray, cJSON_CreateString("01"));
    cJSON_AddItemToObject(device, "identifiers", identifiersArray);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    // 打印生成的 JSON 字符串
    // printf("%s\n", jsonString);
    mqtt_client_send(MQTT_PUB_TOPIC_STR_ILLU, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_pm25_value_send(int value)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加 CO2 数据
    cJSON_AddNumberToObject(root, "pm25", value);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    mqtt_client_send(MQTT_PUB_TOPIC_STR_VAULE_PM25, jsonString, strlen(jsonString));
    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_co2_value_send(int value)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加 CO2 数据
    cJSON_AddNumberToObject(root, "pm25", value);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    mqtt_client_send(MQTT_PUB_TOPIC_STR_VAULE_CO2, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_pm10_value_send(int value)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加 CO2 数据
    cJSON_AddNumberToObject(root, "pm25", value);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    mqtt_client_send(MQTT_PUB_TOPIC_STR_VAULE_PM10, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_pm1_0_value_send(int value)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加 CO2 数据
    cJSON_AddNumberToObject(root, "pm25", value);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    mqtt_client_send(MQTT_PUB_TOPIC_STR_VAULE_PM1_0, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_pub_illu_value_send(int value)
{
    // 创建 JSON 对象
    cJSON* root = cJSON_CreateObject();

    // 添加 CO2 数据
    cJSON_AddNumberToObject(root, "pm25", value);

    // 将 JSON 转换为字符串
    char* jsonString = cJSON_Print(root);

    mqtt_client_send(MQTT_PUB_TOPIC_STR_VAULE_ILLU, jsonString, strlen(jsonString));

    // 释放内存
    free(jsonString);
    cJSON_Delete(root);
}

void mqtt_client_system_init(void)
{
    int rc = 0;

    // 网络初始化
    NetworkInit(&n);
    NetworkConnect(&n, MQTT_ADDRESS, MQTT_PORT);

    // MQTT初始化
    MQTTClientInit(&mqtt_client, &n, 30000, buf, 1000, readbuf, 1000);

    // MQTT 连接
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.willFlag = 1;
    data.MQTTVersion = 4;
    data.clientID.cstring = "test";
    data.username.cstring = null;
    data.password.cstring = null;

    data.keepAliveInterval = 120;
    data.cleansession = 1;

    data.will.message.cstring = "offline";
    data.will.qos = 1;
    data.will.retained = 0;
    data.will.topicName.cstring = "homeassistant/sensor/status";

    rc = MQTTConnect(&mqtt_client, &data);

    if (rc != SUCCESS) {
        printf("MQTT connect fail!\r\n");
        return 0;
    }

    // rc = MQTTSubscribe(&mqtt_client, MQTT_SUB_TOPIC_STR, 2, messageArrived);

    // if (rc != SUCCESS) {
    //     printf("Message MQTTSubscribe failed with code %d\n", rc);
    // }

    // rc = MQTTSubscribe(&mqtt_client, "blemesh_reset", 2, messageArrived_reset);

    // if (rc != SUCCESS) {
    //     printf("Message MQTTSubscribe failed with code %d\n", rc);
    // }

    // rc = MQTTSubscribe(&mqtt_client, "/sys/a1fAL0ry7Sd/jKa5nPhF7ij0QYq3otuw/thing/service/set_hsl_color", 2, messageArrived_color);
    // if (rc != SUCCESS) {
    //     printf("Message MQTTSubscribe failed with code %d\n", rc);
    // }
    // rc = MQTTSubscribe(&mqtt_client, "/sys/a1fAL0ry7Sd/jKa5nPhF7ij0QYq3otuw/thing/service/set_onoff", 2, messageArrived_setonoff);
    // if (rc != SUCCESS) {
    //     printf("Message MQTTSubscribe failed with code %d\n", rc);
    // }
}

void wifi_connect_success(void)
{
    printf("wifi_connect_success\r\n");
    mqtt_start_flag = 0;
}

extern xQueueHandle mqtt_queue;
TaskHandle_t mqtt_yield_xhandle;

void mqtt_yield_process(void* msg)
{
    int rc = 0;

    while (1) {
        if ((rc = MQTTYield(&mqtt_client, 1000)) != 0) {
            MQTTDisconnect(&mqtt_client);
            FreeRTOS_disconnect(&n);
            mqtt_client_system_init();
        }
        vTaskDelay(pdMS_TO_TICKS(1));
    }
}

typedef struct
{
    uint32_t illu_value;    // 光照值    设备地址1
    uint16_t smoggy_status; //烟雾状态   设备地址2
    uint16_t pm1_0_value;   // 设备地址3
    uint16_t pm2_5_value;
    uint16_t pm10_value;
    uint16_t temp_value;     //温度
    uint16_t humidity_value; //温度
    uint16_t co2_value;      //温度
} disp_data_t;

void mqtt_task_process(void* msg)
{
    disp_data_t mqtt_value;
    printf("mqtt_task_process\r\n");
    wifi_callback_register(wifi_connect_success);
    my_wifi_connect("ShowRoomWiFi", "xuhong12345678");
    while (mqtt_start_flag) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
    mqtt_client_system_init();

    xTaskCreate(mqtt_yield_process, (char*)"mqtt_yield_process", 1024, NULL, 16, &mqtt_yield_xhandle);

    mqtt_pub_payload_illu_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_payload_pm1_0_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_payload_pm10_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_payload_co2_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_payload_pm25_send();
    vTaskDelay(pdMS_TO_TICKS(100));

    mqtt_pub_enable_illu_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_enable_pm1_0_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_enable_pm10_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_enable_co2_send();
    vTaskDelay(pdMS_TO_TICKS(100));
    mqtt_pub_enable_pm25_send();
    vTaskDelay(pdMS_TO_TICKS(100));

    while (1) {
        if (xQueueReceive(mqtt_queue, &mqtt_value, portMAX_DELAY)) {
            mqtt_pub_pm25_value_send(mqtt_value.pm2_5_value);
            vTaskDelay(pdMS_TO_TICKS(100));
            mqtt_pub_co2_value_send(mqtt_value.co2_value);
            vTaskDelay(pdMS_TO_TICKS(100));
            mqtt_pub_pm10_value_send(mqtt_value.pm10_value);
            vTaskDelay(pdMS_TO_TICKS(100));
            mqtt_pub_pm1_0_value_send(mqtt_value.pm1_0_value);
            vTaskDelay(pdMS_TO_TICKS(100));
            mqtt_pub_illu_value_send(mqtt_value.illu_value);
            vTaskDelay(pdMS_TO_TICKS(100));
        }
    }
}
